import json
import os
import logging
import struct

import sqlite3
import time

import udsoncan
from openpyxl.reader.excel import load_workbook
from loguru import logger
from udsoncan import NegativeResponseException, DataIdentifier
from udsoncan.client import Client
from udsoncan.Response import Response

from sdk.cfg import tp_funcaddr, tp_physaddr

file = "DTC.xlsx"


def conversion_json(excel_path, sheets_names: list = None, storage_filepath=None):
    """
    :param excel_path: excel文件地址
    :param sheets_names: 列表传入指定sheet页 不传默认所有
    :param storage_filepath: 保存json文件地址 不传默认当前文件夹
    :return:
    """
    global file_data, index, temp_dict
    wb = load_workbook(excel_path)
    if sheets_names is None:
        sheets_names = wb.sheetnames
    for sheet_name in sheets_names:
        data = wb[sheet_name]
        temp_list = []
        temp_dict = {}
        for i in range(1, data.max_row):
            for j in range(1, data.max_column + 1):
                title_data = data.cell(row=i + 1, column=1).value
                value_data = data.cell(row=i + 1, column=2).value
                if title_data is not None and value_data is not None:
                    if sheet_name == 'dtc':
                        if title_data.startswith("0x"):
                            temp_dict[title_data.lower()] = value_data
                        else:
                            temp_dict['0x' + title_data.lower()] = value_data
                    else:
                        if title_data.startswith("0x"):
                            temp_dict[int(title_data.lower())] = value_data
                        else:
                            temp_dict[int('0x' + title_data, base=16)] = value_data
                else:
                    continue

        temp_list.append(temp_dict)
        index = 0
        file_data = ''
        for i in temp_list:
            json_data = json.dumps(temp_dict, indent=4, ensure_ascii=False)
            index = index + 1
            file_data = file_data + json_data + '\r\n'
            if storage_filepath is None:
                storage_filepath = os.path.dirname(__file__)
            with open(storage_filepath + r"/{}.json".format(sheet_name), "w+", encoding="GB2312") as f:
                f.write(file_data)


class Diagnostics:

    def __init__(self, client, stack, MyLogger=None):
        self.tp_funcaddr = tp_funcaddr
        self.tp_physaddr = tp_physaddr
        self.client = client
        self.stack = stack
        # conversion_json(file, storage_filepath='sdk/json_file')
        self.logger = MyLogger
        _DTC_file = open('sdk/json_file/dtc.json', 'r')
        self._DTCList = json.load(_DTC_file)
        _DTC_file.close()
        DID_file = open('sdk/json_file/did.json', 'r')
        self._DIDList = json.load(DID_file)
        DID_file.close()

    def diag_change_address(self, phys, func):
        self.tp_physaddr = phys
        self.tp_funcaddr = func

    def diag_change_client(self, client, stack):
        self.client = client
        self.stack = stack

    def _inspect(self):
        try:
            self.stack.set_address(self.tp_physaddr)
            self.client.change_session(1)
        except:
            self.logger.error('设备无通讯或未打开')

    def readDTC(self):
        self._inspect()
        try:
            res = self.client.get_dtc_by_status_mask(9)
            dtc_list = res.service_data.dtcs
            if dtc_list is not None:
                for i in range(len(dtc_list)):
                    if (hex(dtc_list[i].id)) in self._DTCList.keys():
                        self.logger.info(self._DTCList[hex(dtc_list[i].id)])
                    else:
                        self.logger.info("无故障")
            self.logger.info('读取成功')
        except:
            self.logger.debug('读取失败,请重试')

    def printRet(self, ret):
        value = ''
        for i in ret:
            value = value + str(i, encoding="utf-8")
        self.logger.info(value)

    def readAPPVersion(self):
        self._inspect()
        ret = self.client.read_data_by_identifier_first(DataIdentifier.SystemSupplierECUSoftwareVersionNumber)
        print(ret)
        # self.printRet(ret)

    def readBTLVersion(self):
        self._inspect()
        ret = self.client.read_data_by_identifier_first(DataIdentifier.ECUManufacturingDate)
        print(ret)
        self.printRet(ret)

    def readHWVersion(self):
        self._inspect()
        ret = self.client.read_data_by_identifier_first(DataIdentifier.SystemSupplierECUHardwareVersionNumber)
        self.printRet(ret)

    def writeVIN(self):
        self.stack.set_address(self.tp_physaddr)
        self.client.change_session(3)
        self.client.unlock_security_access(0x01)
        self.client.write_data_by_identifier(did=0xF190,
                                             value=(
                                                 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
                                                 0x01, 0x01, 0x01, 0x01, 0x01))

    def safetyAccess(self):
        self.client.change_session(3)
        time.sleep(1)
        self.client.unlock_security_access(0x01)

    def ecuRest(self):
        self._inspect()
        try:
            self.client.ecu_reset(1)
            self.logger.info('复位成功')
        except:
            self.logger.info('复位失败')

    def clearDTC(self):
        self._inspect()
        try:
            self.client.clear_dtc(0xFFFFFF)
            self.logger.info('清除成功')
        except:
            self.logger.info('清除失败')
